package com.jdy.utils;

import java.lang.reflect.*;

/**
 * Spring 框架学习
 * <p>
 * Description: spring-mvc
 * <p>
 * Created by 49897 on 2020/4/2 12:56
 */
public class ReflectionUtils {

    private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];

    public static void handleReflectionException(Exception e) {
        if (e instanceof NoSuchMethodException) {
            throw new IllegalStateException("Method not found: " + e.getMessage());
        }

        if (e instanceof IllegalAccessException) {
            throw new IllegalStateException("Could not access method or field: " + e.getMessage());
        }

        if (e instanceof InvocationTargetException) {
            handleInvocationTargetException((InvocationTargetException) e);
        }

        if (e instanceof RuntimeException) {
            throw (RuntimeException) e;
        }

        throw new UndeclaredThrowableException(e);
    }

    public static void handleInvocationTargetException(InvocationTargetException e) {
        rethrowRuntimeException(e.getTargetException());
    }

    private static void rethrowRuntimeException(Throwable throwable) {
        if (throwable instanceof RuntimeException) {
            throw (RuntimeException) throwable;
        }

        if (throwable instanceof Error) {
            throw (Error) throwable;
        }

        throw new UndeclaredThrowableException(throwable);
    }

    public static Object getField(Field field, Object target) {
        try {
            return field.get(target);
        } catch (IllegalAccessException e) {
            handleReflectionException(e);
        }
        throw new IllegalStateException("Should never get here");
    }

    public static Object invokeMethod(Method method, Object target) {
        return invokeMethod(method, target, EMPTY_OBJECT_ARRAY);
    }

    public static Object invokeMethod(Method method, Object target, Object... args) {
        try {
            return method.invoke(target, args);
        } catch (Exception e) {
            handleReflectionException(e);
        }
        throw new IllegalStateException("Should never get here");
    }

    public static void makeAccessible(Constructor<?> ctor) {
        if ((!Modifier.isPublic(ctor.getModifiers()) || !Modifier.isPublic(ctor.getDeclaringClass().getModifiers())) && !ctor.isAccessible()) {
            ctor.setAccessible(true);
        }
    }
}
